package io.shuttle.mbe.api.impl

import android.os.CountDownTimer
import io.shuttle.mbe.api.Alarms
import io.shuttle.mbe.api.Events
import io.shuttle.mbe.api.types.Value1Function
import io.shuttle.mbe.api.types.VoidFunction
import io.shuttle.mbe.core.Promise


class AlarmsImpl(
    override var onAlarm: Events.Event<Value1Function<Alarms.Alarm>>
) : Alarms {
    private val alarmMap = mutableMapOf<Alarms.Alarm, CountDownTimer>()

    override fun clear(
        name: String?,
        callback: Value1Function<Boolean>?
    ): Promise<Boolean> {
        if (name.isNullOrBlank()) {
            return Promise.reject(IllegalArgumentException("name is required"))
        }
        val target = alarmMap.keys.find { it.name == name }
        val result = target?.let { alarmMap.remove(it) != null } ?: false
        callback?.invoke(result)
        return Promise.resolve(result)
    }

    override fun clearAll(callback: Value1Function<Boolean>?): Promise<Boolean> {
        val result = alarmMap.isNotEmpty()
        alarmMap.clear()
        callback?.invoke(result)
        return Promise.resolve(result)
    }

    override fun create(
        name: String?,
        alarmInfo: Alarms.AlarmCreateInfo,
        callback: VoidFunction?
    ): Promise<Void> {
        if (name.isNullOrBlank()) {
            return Promise.reject(IllegalArgumentException("name is required"))
        }
        if (alarmInfo.delayInMinutes == null && alarmInfo.`when` == null) {
            return Promise.reject(IllegalArgumentException("delayInMinutes or when is required"))
        }

        val alarm = Alarms.Alarm(alarmInfo.periodInMinutes, alarmInfo.delayInMinutes ?: 0, name)
        val delay = (alarmInfo.delayInMinutes
            ?: (alarmInfo.`when`!!.toLong() - System.currentTimeMillis())).toLong() * 60000
        val period = (alarmInfo.periodInMinutes ?: 0).toLong() * 60000
        alarmMap[alarm] = object : CountDownTimer(delay, period) {
            override fun onTick(millisUntilFinished: Long) {
            }

            override fun onFinish() {
            }
        }.also { it.start() }
        callback?.invoke()
        return Promise.resolve(null)
    }

    override fun get(
        name: String?,
        callback: Value1Function<Alarms.Alarm?>?
    ): Promise<Alarms.Alarm?> {
        if (name.isNullOrBlank()) {
            return Promise.reject(IllegalArgumentException("name is required"))
        }
        val target = alarmMap.keys.find { it.name == name }
        callback?.invoke(target)
        return Promise.resolve(target)
    }

    override fun getAll(callback: Value1Function<List<Alarms.Alarm>>?): Promise<List<Alarms.Alarm>> {
        val result = alarmMap.keys.toList()
        callback?.invoke(result)
        return Promise.resolve(result)
    }
}